package com.xh.bussiness.exam.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xh.bussiness.exam.bean.dto.PaperChapterTestDto;
import com.xh.bussiness.exam.bean.dto.PaperQuestionTestDetailDto;
import com.xh.bussiness.exam.bean.dto.PaperTestDetailDto;
import com.xh.bussiness.exam.bean.dto.PaperTestDto;
import com.xh.bussiness.exam.bean.request.ErrorQuestionPaperTestRequest;
import com.xh.bussiness.exam.bean.request.PaperQuestionTestDetailSaveRequest;
import com.xh.bussiness.exam.bean.request.PaperTestQueryRequest;
import com.xh.bussiness.exam.bean.request.PaperTestSaveRequest;
import com.xh.bussiness.exam.bean.request.UserErrorQuestionSaveRequest;
import com.xh.bussiness.exam.constant.PaperPublishConstant;
import com.xh.bussiness.exam.constant.PaperTestConstant;
import com.xh.bussiness.exam.dao.PaperChapterTestMapper;
import com.xh.bussiness.exam.dao.PaperPublishMapper;
import com.xh.bussiness.exam.dao.PaperQuestionTestDetailMapper;
import com.xh.bussiness.exam.dao.PaperTestMapper;
import com.xh.bussiness.exam.model.PaperChapterTest;
import com.xh.bussiness.exam.model.PaperPublish;
import com.xh.bussiness.exam.model.PaperQuestionTestDetail;
import com.xh.bussiness.exam.model.PaperTest;
import com.xh.bussiness.exam.model.UserErrorQuestion;
import com.xh.bussiness.exam.model.UserErrorQuestionPaperQuestion;
import com.xh.bussiness.exam.service.*;
import com.xh.bussiness.tiku.bean.dto.AnswerResultDto;
import com.xh.bussiness.tiku.bean.dto.PaperDto;
import com.xh.bussiness.tiku.bean.dto.QuestionDto;
import com.xh.bussiness.tiku.bean.request.PaperQuestionSaveRequest;
import com.xh.bussiness.tiku.bean.request.PaperSaveRequest;
import com.xh.bussiness.tiku.bean.request.QuestionQueryRequest;
import com.xh.bussiness.tiku.constant.PaperConstant;
import com.xh.bussiness.tiku.constant.QuestionConstant;
import com.xh.bussiness.tiku.dao.PaperMapper;
import com.xh.bussiness.tiku.model.Paper;
import com.xh.bussiness.tiku.model.Question;
import com.xh.bussiness.tiku.model.QuestionKnowledge;
import com.xh.bussiness.tiku.service.IPaperService;
import com.xh.bussiness.tiku.service.IQuestionKnowledgeService;
import com.xh.bussiness.tiku.service.IQuestionService;
import com.xh.bussiness.tiku.util.QuestionUtils;
import com.xh.core.bean.ServiceResultBean;
import com.xh.core.bean.XhPage;
import com.xh.core.service.impl.BaseServiceImpl;
import com.xh.core.util.ObjectUtils;
import com.xh.core.util.StringUtils;
import com.xh.core.util.UserUtils;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/*
 * @Author daiwei
 * @Description
 * @Date 2019/4/10 14:03
 **/
@Service
public class PaperTestServiceImpl extends BaseServiceImpl<PaperTestMapper,PaperTest> implements IPaperTestService {

    @Autowired
    private IQuestionService questionService;
    @Autowired
    private IPaperService paperService;
    @Autowired
    private IPaperChapterTestService paperChapterTestService;
    @Autowired
    private IPaperQuestionTestDetailService paperQuestionTestDetailService;
    @Autowired
    private IPaperPublishService paperPublishService;
    @Autowired
    private IUserErrorQuestionService userErrorQuestionService;
    @Autowired
    private PaperQuestionTestDetailMapper paperQuestionTestDetailMapper;
    @Autowired
    private PaperChapterTestMapper paperChapterTestMapper;
    @Autowired
    private PaperTestMapper paperTestMapper;
    @Autowired
    private PaperPublishMapper paperPublishMapper;
    @Autowired
    private IQuestionKnowledgeService questionKnowledgeService;
    @Autowired
    private IUserErrorQuestionPaperQuestionService userErrorQuestionPaperQuestionService;
    
    @Override
    public ServiceResultBean<PaperTestDto> addNewTest(PaperTestSaveRequest bean) {
        if(StringUtils.isEmpty(bean.getPaperPublishId())){
            return new ServiceResultBean<PaperTestDto>("试卷发布ID不能为空");
        }
        PaperPublish paperPublish=this.paperPublishMapper.selectById(bean.getPaperPublishId());
        if(paperPublish.getPublishStatus().equals(PaperPublishConstant.PublishStatuc.UN_PUBLISH)){
            return new ServiceResultBean<PaperTestDto>("当前试卷为未发布状态");
        }
        Date now=new Date();
        if((paperPublish.getOpenTime()!=null&&paperPublish.getOpenTime().compareTo(now)<=0)
                &&(paperPublish.getCloseTime()!=null&&paperPublish.getCloseTime().compareTo(now)>=0)){
            return new ServiceResultBean<PaperTestDto>("当前试卷不在开放时间区间内");
        }
        if(paperPublish.getLogined().equals(PaperPublishConstant.LoginRequired.YES)){
            if(StringUtils.isEmpty(UserUtils.getCurrentUserId())){
                return new ServiceResultBean<PaperTestDto>("当前试卷需要登录后访问");
            }
        }else{
            //不需要登录作答时，如果没有登录且没有作答人信息，不允许访问
            if(StringUtils.isEmpty(UserUtils.getCurrentUserId())){
                if(StringUtils.isEmpty(bean.getMobile())||StringUtils.isEmpty(bean.getNickname())){
                    return new ServiceResultBean<PaperTestDto>("当前试卷作答需要指定作答人手机及姓名");
                }
            }
        }
        PaperTest paperTest=null;
        QueryWrapper<PaperTest> paperTestQw=new QueryWrapper<>();
        if(StringUtils.isEmpty(UserUtils.getCurrentUserId())){
            //新建一个
            paperTestQw.eq("paper_publish_id",bean.getPaperPublishId());
            paperTestQw.eq("mobile",bean.getMobile().trim());
            paperTestQw.eq("nickname",bean.getNickname().trim());
            paperTestQw.orderByDesc("create_time");
        }else{
            paperTestQw.eq("paper_publish_id",bean.getPaperPublishId());
            paperTestQw.eq("creator_id",UserUtils.getCurrentUserId());
            paperTestQw.orderByDesc("create_time");
        }
        paperTest=this.dao.selectOne(paperTestQw);
        if(paperTest==null){
            paperTest=createNewPaperTest(bean);
        }else {
            if (paperPublish.getRepeatType().equals(PaperPublishConstant.RepeatType.NO_REPEAT)) {

            } else if (paperPublish.getRepeatType().equals(PaperPublishConstant.RepeatType.REWRITE)) {
                this.dao.deleteById(paperTest.getId());
                paperTest=createNewPaperTest(bean);
            } else if (paperPublish.getRepeatType().equals(PaperPublishConstant.RepeatType.NEW)) {
                paperTest=createNewPaperTest(bean);
            }
        }

        return new ServiceResultBean<PaperTestDto>(null,getPaperTestById(paperTest.getId()));
    }

    @Override
    public ServiceResultBean<PaperTestDto> addRandomNewTest(QuestionQueryRequest bean, Integer paperType) {
        List<String> questions = bean.getQuestions() == null ? questionService.queryQuesitonRandom(bean) :  bean.getQuestions();

        PaperSaveRequest paperSaveRequest=new PaperSaveRequest();
        paperSaveRequest.setQuestionCount(questions.size());
        paperSaveRequest.setSubjectId(bean.getSubject());
        paperSaveRequest.setType(paperType);
        List<PaperQuestionSaveRequest> paperQuestions=new ArrayList<>();
        for(String question:questions){
            PaperQuestionSaveRequest paperQuestionSaveRequest=new PaperQuestionSaveRequest();
            paperQuestionSaveRequest.setQuestionId(question);
            paperQuestionSaveRequest.setScore(0);
            paperQuestions.add(paperQuestionSaveRequest);
        }
        paperSaveRequest.setQuestions(paperQuestions);
        PaperDto paper=paperService.addPaper(null,paperSaveRequest);

        PaperTest paperTest=null;
        QueryWrapper<PaperTest> paperTestQw=new QueryWrapper<>();
        paperTestQw.eq("type",paperType);
        paperTestQw.eq("creator_id",UserUtils.getCurrentUserId());
        paperTestQw.orderByDesc("create_time");

        PaperTestSaveRequest paperTestSaveRequest=new PaperTestSaveRequest();
        paperTestSaveRequest.setPaperId(paper.getId());
        paperTest=this.selectFirst(paperTestQw);
        if(paperTest==null){
            paperTest=createNewPaperTest(paperTestSaveRequest);
        }

        return new ServiceResultBean<PaperTestDto>(null,getPaperTestById(paperTest.getId()));
    }

    @Override
    public String addQuestionTestDetail(PaperQuestionTestDetailSaveRequest bean) {
        //判断当前是否已经提交，提交后不可再修改答案，否则可以覆盖之前作答记录
        PaperTest paperTest=this.dao.selectById(bean.getPaperTestId());
        if(paperTest.getSubmitted().equals(PaperTestConstant.SUBMITTED.SUBMITTED)){
            return "当前测评已提交，不能继续作答";
        }
        //验证是不是有效的试卷、练习

        //检测已作答结果
        QueryWrapper<PaperQuestionTestDetail> qwDetail=new QueryWrapper<>();
        qwDetail.eq("paper_test_id",bean.getPaperTestId());
        if(!StringUtils.isEmpty(bean.getPaperChapterTestId())) {
            qwDetail.eq("paper_chapter_test_id", bean.getPaperChapterTestId());
        }
        qwDetail.eq("question_id",bean.getQuestionId());
        PaperQuestionTestDetail paperQuestionTestDetail=this.paperQuestionTestDetailMapper.selectOne(qwDetail);
        if(paperQuestionTestDetail==null){
            paperQuestionTestDetail=new PaperQuestionTestDetail();
        }
        ObjectUtils.copyNonNullProperties(bean,paperQuestionTestDetail);

        QuestionDto questionDto=questionService.getQuestion(paperQuestionTestDetail.getQuestionId(),paperQuestionTestDetail.getQuestionVersion(),true,false,false,false,false);

        AnswerResultDto answerResultDto= QuestionUtils.checkAnswer(questionDto.getType(),questionDto.getRightAnswer().toJSONString(),bean.getSubmitAnswer());

        paperQuestionTestDetail.setAnswerResult(answerResultDto.getResult());
        paperQuestionTestDetail.setTotalBlankCount(answerResultDto.getTotalBlankCount());
        paperQuestionTestDetail.setTotalRightBlankCount(answerResultDto.getTotalRightBlankCount());

        paperQuestionTestDetail.insertOrUpdate();

        if(!StringUtils.isEmpty(paperQuestionTestDetail.getPaperChapterTestId())){
            paperChapterTestMapper.rebuildData(paperQuestionTestDetail.getPaperChapterTestId());
        }

        if(!answerResultDto.getRight()){
            UserErrorQuestionSaveRequest userErrorQuestionSaveRequest=new UserErrorQuestionSaveRequest();
            userErrorQuestionSaveRequest.setUserId(UserUtils.getCurrentUserId());
            userErrorQuestionSaveRequest.setSubjectId(questionDto.getSubjectId());
            userErrorQuestionSaveRequest.setGradeId(paperTest.getGradeId());
            userErrorQuestionSaveRequest.setQuestionId(questionDto.getId());
            userErrorQuestionSaveRequest.setQuestionVersion(questionDto.getCurrentVersion());
            userErrorQuestionSaveRequest.setUserAnswer(bean.getSubmitAnswer());
            userErrorQuestionService.addUserErrorQuestion(userErrorQuestionSaveRequest);
        }

        paperTestMapper.rebuildDataById(paperQuestionTestDetail.getPaperTestId());
        return null;
    }

    /**
     * 创建测评记录
     * @param bean
     * @return
     */
    private PaperTest createNewPaperTest(PaperTestSaveRequest bean){
        PaperDto paperDto=paperService.getPaper(bean.getPaperId());
        PaperPublish paperPublish=null;
        if(!StringUtils.isEmpty(bean.getPaperPublishId())){
            paperPublish=paperPublishMapper.selectById(bean.getPaperPublishId());
        }else{
        	paperPublish = new PaperPublish();
    		paperPublish.setOpenTime(new Date());
    		paperPublish.setStudentId(bean.getStudentId());
    		paperPublish.setType(paperDto.getType());
    		paperPublish.setPublishStatus(1);
    		paperPublish.setLogined(1);
    		paperPublish.setRepeatType(0);
    		paperPublish.setPaperId(paperDto.getId());
    		paperPublish.setSubjectId(paperDto.getSubjectId());
    		paperPublishService.insert(paperPublish);
        }
        PaperTest paperTest=new PaperTest();
        ObjectUtils.copyNonNullProperties(paperDto,paperTest);
        paperTest.setPaperPublishId(paperPublish.getId());
        paperTest.setPaperId(bean.getPaperId());
   //     paperTest.setPaperVersion(paperDto.getCurrentVersion());
        paperTest.setMobile(bean.getMobile()==null?null:bean.getMobile().trim());
        paperTest.setNickname(bean.getNickname()==null?null:bean.getNickname().trim());
        paperTest.setChapterCount(0);
        paperTest.setTotalQuestionCount(paperDto.getQuestionCount());
        paperTest.setStudentId(UserUtils.getCurrentUserId());
        paperTest.setId(null);
        this.dao.insert(paperTest);
        return paperTest;
    }

    @Override
    public PaperTestDto getPaperTestById(String id) {
        PaperTestDto paperTestDto=this.getById(id,PaperTestDto.class);
        PaperDto paperDto=paperService.getPaper(paperTestDto.getPaperId());
        paperTestDto.setPaper(paperDto);

        if(paperDto.getChapterCount()>0){
            List<PaperChapterTestDto> chapterTests;
            QueryWrapper<PaperChapterTest> qw=new QueryWrapper<>();
            qw.eq("paper_test_id",paperTestDto.getId());
            chapterTests=paperChapterTestService.selectList(qw,PaperChapterTestDto.class);

            for(PaperChapterTestDto paperChapterTestDto:chapterTests){
                List<PaperQuestionTestDetailDto> questionTestDetails;
                QueryWrapper<PaperQuestionTestDetail> qwd=new QueryWrapper<>();
                qw.eq("paper_chapter_test_id",paperChapterTestDto.getId());
                questionTestDetails=paperQuestionTestDetailService.selectList(qwd,PaperQuestionTestDetailDto.class);
                paperChapterTestDto.setQuestionTestDetails(questionTestDetails);
            }
            paperTestDto.setChapterTests(chapterTests);
        }else{
            List<PaperQuestionTestDetailDto> questionTestDetails;
            QueryWrapper<PaperQuestionTestDetail> qw=new QueryWrapper<>();
            qw.eq("paper_test_id",paperTestDto.getId());
            questionTestDetails=paperQuestionTestDetailService.selectList(qw,PaperQuestionTestDetailDto.class);
            paperTestDto.setQuestionTestDetails(questionTestDetails);
        }
        return paperTestDto;
    }

    @Override
    public PaperTestDto getPaperTestByUserAndPaperId(String userId, String paperId) {
        return null;
    }

    @Override
    public XhPage<PaperTestDto> queryPagePaperTest(XhPage page, PaperTestQueryRequest bean) {
        QueryWrapper<PaperTest> qw=new QueryWrapper<>();
        if(!StringUtils.isEmpty(bean.getSubjectId())){
            qw.eq("subject_id",bean.getSubjectId());
        }
        if(!StringUtils.isEmpty(bean.getSubjectId())){
            qw.eq("grade_id",bean.getGradeId());
        }
        if(!StringUtils.isEmpty(bean.getSubjectId())){
            qw.eq("type",bean.getType());
        }
        if(bean.getSubmitted()!=null) {
            qw.eq("submitted", bean.getSubmitted());
        }

        page=(XhPage<PaperTestDto>) this.selectPage(page,qw,PaperTestDto.class);
        return page;
    }

	@Override
	public PaperTestDetailDto getTestDetailById(PaperQuestionTestDetailSaveRequest bean) {
		QueryWrapper<PaperQuestionTestDetail> queryWrapper = new QueryWrapper<PaperQuestionTestDetail>();
		queryWrapper.eq("paper_test_id",bean.getPaperTestId());
		queryWrapper.eq("question_id", bean.getQuestionId());
		queryWrapper.eq("creator_id", UserUtils.getCurrentUserId());
		PaperQuestionTestDetail detail = paperQuestionTestDetailMapper.selectOne(queryWrapper);
		PaperTestDetailDto detailDto = new PaperTestDetailDto();
		ObjectUtils.copyNonNullProperties(detail, detailDto);
		QuestionDto question = questionService.getQuestion(bean.getQuestionId(), detail.getQuestionVersion());
		detailDto.setQuestion(question);
		return detailDto;
	}

	@Override
	public String submitTest(List<PaperQuestionTestDetail> details) {
		//判断当前是否已经提交，提交后不可再修改答案，否则可以覆盖之前作答记录
        PaperTest paperTest = super.getById(details.get(0).getPaperTestId());
        if(paperTest.getSubmitted().equals(PaperTestConstant.SUBMITTED.SUBMITTED)){
            return "当前测评已提交，不能继续作答";
        }
		Integer answerTime = 0;
		for(PaperQuestionTestDetail detail : details){
			answerTime+=detail.getUsedTime();
			//判断每道题是否正确
			QuestionDto question = questionService.getQuestion(detail.getQuestionId(), detail.getQuestionVersion(), true,false,false,false,false);
			AnswerResultDto answerResult = QuestionUtils.checkAnswer(question.getType(), question.getRightAnswer().toJSONString(), detail.getSubmitAnswer());
			detail.setTotalBlankCount(answerResult.getTotalBlankCount());
			detail.setTotalRightBlankCount(answerResult.getTotalRightBlankCount());
			detail.setAnswerResult(answerResult.getResult());
			// 记录错题
			// 如果题目错了，已有的错题，次数+1，没有的新增
			if(!answerResult.getRight()){
	            UserErrorQuestionSaveRequest userErrorQuestionSaveRequest=new UserErrorQuestionSaveRequest();
	            userErrorQuestionSaveRequest.setUserId(UserUtils.getCurrentUserId());
	            userErrorQuestionSaveRequest.setSubjectId(question.getSubjectId());
	            userErrorQuestionSaveRequest.setQuestionId(question.getId());
	            userErrorQuestionSaveRequest.setQuestionVersion(question.getCurrentVersion());
	            userErrorQuestionSaveRequest.setUserAnswer(detail.getSubmitAnswer());
	            userErrorQuestionService.addUserErrorQuestion(userErrorQuestionSaveRequest);
	        }
		}
		// 更新测试的提交状态
		paperTest.setUsedTime(answerTime);
		paperTest.setSubmitted(PaperTestConstant.SUBMITTED.SUBMITTED);
		super.update(paperTest);
		paperQuestionTestDetailService.batchInsert(details);
		
		return null;
	}

	@Override
	public PaperTestDto addErrorQuestionPaperTest(ErrorQuestionPaperTestRequest bean) {
		PaperTestDto paperTestDto = null;
		// 根据知识点练习
		if(!CollectionUtils.isEmpty(bean.getKnowledgeIds())){
			QuestionQueryRequest paperTest = new QuestionQueryRequest();
			paperTest.setKnowledgePoints(bean.getKnowledgeIds());
			paperTest.setRandomCount(bean.getRandomCount());
			paperTest.setDifficult(bean.getDifficult());
			paperTestDto = addRandomNewTest(paperTest, PaperConstant.TYPE.ERROR_QUESTION_TEST).getData();
		}else{
			// 根据错题练习
			List<Question> errorQuestions = bean.getErrorQuestions();
			List<String> ids = new ArrayList<String>();
			Map<String,List<String>> questionIds=new HashMap<String,List<String>>();
			List<String> allQuestions = new ArrayList<String>();
			errorQuestions.forEach(q->{
				QueryWrapper<QuestionKnowledge> qw = new QueryWrapper<QuestionKnowledge>();
				qw.eq("question_id", q.getId());
				List<QuestionKnowledge> knowledges = questionKnowledgeService.queryByCondition(qw);
				List<String> knowledgeIds = new ArrayList<String>();
				knowledges.forEach(k->{
					knowledgeIds.add(k.getId());
				});
				QuestionQueryRequest request = new QuestionQueryRequest();
				request.setKnowledgePoints(knowledgeIds);
				request.setRandomCount(bean.getRandomCount());
				request.setDifficult(bean.getDifficult());
				List<String> questions = questionService.queryQuesitonRandom(request);
				questionIds.put(q.getId(), questions);
				allQuestions.add(q.getId());
				allQuestions.addAll(questions);
			});
			QuestionQueryRequest paperTest = new QuestionQueryRequest();
			paperTest.setQuestions(allQuestions);
			paperTest.setSubject(bean.getSubject());
			paperTestDto = addRandomNewTest(paperTest, PaperConstant.TYPE.ERROR_QUESTION_TEST).getData();
			
			// 生成错题和对应习题的关系
			List<UserErrorQuestionPaperQuestion> list = new ArrayList<UserErrorQuestionPaperQuestion>();
			for(Entry<String, List<String>> entry : questionIds.entrySet()){
				entry.getValue().forEach(id->{
					UserErrorQuestionPaperQuestion uqq = new UserErrorQuestionPaperQuestion();
					uqq.setQuestionId(entry.getKey());
					uqq.setErrorQuestionId(entry.getKey());
					list.add(uqq);
				});
			}
			userErrorQuestionPaperQuestionService.batchInsert(list);
		}

		return paperTestDto;
	}
	
	@Override
    public List<PaperQuestionTestDetail> queryStudentTestDetail(String studentId, String startDate, String endDate, Integer paperType) {
        return this.dao.queryStudentTestDetail(studentId, startDate, endDate, paperType);
    }
}
